﻿namespace HelpersTestProject
{
    using System;
    using System.Configuration;
    using System.Data;
    using System.Data.SqlClient;
    using System.IO;
    using System.Text;

    using Microsoft.TeamFoundation.TestManagement.Client;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    using UITest.Helpers.DataAccess;
    using UITest.Helpers.TFS;

    /// <summary>
    ///     The tfs library test.
    /// </summary>
    [TestClass]
    public class TFSLibraryTest
    {
        #region Fields

        /// <summary>
        ///     The db test suite table name.
        /// </summary>
        public string DBTestSuiteTableName = "xxxxxxx";

        /// <summary>
        ///     The test plan object.
        /// </summary>
        public ITestPlan TestPlanObject;

        /// <summary>
        ///     The test suite data table.
        /// </summary>
        public DataTable TestSuiteDataTable = new DataTable();

        /// <summary>
        ///     The update date time.
        /// </summary>
        public DateTime UpdateDateTime = DateTime.UtcNow;

        private readonly string connectionString =
            ConfigurationManager.ConnectionStrings["ReportDBConnection"].ConnectionString;

        private readonly string providerName = ConfigurationManager.ConnectionStrings["ReportDBConnection"].ProviderName;

        private TFSLibrary tfs;

        #endregion

        #region Public Properties

        /// <summary>
        ///     Gets or sets the test context.
        /// </summary>
        public TestContext TestContext { get; set; }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        ///     The export all test suite to data table.
        /// </summary>
        [TestMethod]
        public void ExportAllTestSuiteToDataTable()
        {
            this.TestPlanObject = this.tfs.TestPlan.Find(273580);

            this.InitTestSuiteDataTable();

            this.ExportToDataTable(this.TestPlanObject.RootSuite.SubSuites, 0);

            this.ExportHtmlReport();

            this.UpdateTestSuiteDB(this.TestSuiteDataTable);
        }

        /// <summary>
        ///     The export all test suite to data table under specific test suite.
        /// </summary>
        [TestMethod]
        public void ExportAllTestSuiteToDataTableUnderSpecificTestSuite()
        {
            this.InitTestSuiteDataTable();

            int testSuiteId = 123456;
            this.TestPlanObject = this.tfs.TestPlan.Find(987654);
            var testSuite = (IStaticTestSuite)this.tfs.TestSuite.Find(testSuiteId);
            this.ExportToDataTable(testSuite.SubSuites, 0);

            this.ExportHtmlReport();

            this.UpdateTestSuiteDB(this.TestSuiteDataTable);
        }

        /// <summary>
        /// The find test case.
        /// </summary>
        [TestMethod]
        public void FindTestCase()
        {
            int id = 123456;
            ITestCase testcase = this.tfs.TestCase.Find(id);
            Assert.IsNotNull(testcase);
            Assert.AreEqual(id, testcase.Id);
        }

        #endregion

        #region Methods

        /// <summary>
        /// The export datatable to html.
        /// </summary>
        /// <param name="dt">
        /// The dt.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        protected string ExportDatatableToHtml(DataTable dt)
        {
            var strHTMLBuilder = new StringBuilder();
            strHTMLBuilder.Append("<html >");
            strHTMLBuilder.Append("<head>");
            strHTMLBuilder.Append("</head>");
            strHTMLBuilder.Append("<body>");
            strHTMLBuilder.Append(
                "<table border='1px' cellpadding='1' cellspacing='1' bgcolor='lightyellow' style='font-family:Garamond; font-size:smaller'>");

            strHTMLBuilder.Append("<tr >");
            foreach (DataColumn myColumn in dt.Columns)
            {
                strHTMLBuilder.Append("<td >");
                strHTMLBuilder.Append(myColumn.ColumnName);
                strHTMLBuilder.Append("</td>");
            }

            strHTMLBuilder.Append("</tr>");

            foreach (DataRow myRow in dt.Rows)
            {
                strHTMLBuilder.Append("<tr >");
                foreach (DataColumn myColumn in dt.Columns)
                {
                    strHTMLBuilder.Append("<td >");
                    strHTMLBuilder.Append(myRow[myColumn.ColumnName]);
                    strHTMLBuilder.Append("</td>");
                }

                strHTMLBuilder.Append("</tr>");
            }

            // Close tags.  
            strHTMLBuilder.Append("</table>");
            strHTMLBuilder.Append("</body>");
            strHTMLBuilder.Append("</html>");

            string Htmltext = strHTMLBuilder.ToString();

            return Htmltext;
        }

        private void ExportHtmlReport()
        {
            string report = this.ExportDatatableToHtml(this.TestSuiteDataTable);
            string path = string.Format("{0}\\testreport.html", this.TestContext.TestRunResultsDirectory);
            File.WriteAllText(path, report);
            this.TestContext.AddResultFile(path);
        }

        private void ExportToDataTable(ITestSuiteCollection suitesCollection, int depth)
        {
            foreach (IStaticTestSuite childSuite in suitesCollection)
            {
                DataRow dataRow = this.TestSuiteDataTable.NewRow();

                dataRow["TestPlanID"] = this.TestPlanObject.Id;
                dataRow["TestPlanName"] = this.TestPlanObject.Name;
                dataRow["Depth"] = depth;
                dataRow["TestSuiteId"] = childSuite.Id;
                dataRow["TestSuiteTitle"] = childSuite.Title;
                dataRow["TestCaseCount"] = childSuite.TestCaseCount;
                dataRow["ParentTestSuite"] = childSuite.Parent.Id;
                dataRow["LastUpdate"] = this.UpdateDateTime;

                this.TestSuiteDataTable.Rows.Add(dataRow);

                for (int i = 0; i < childSuite.TestCaseCount; i++)
                {
                    DataRow TestCasedataRow = this.TestSuiteDataTable.NewRow();

                    TestCasedataRow["TestPlanID"] = this.TestPlanObject.Id;
                    TestCasedataRow["TestPlanName"] = this.TestPlanObject.Name;
                    TestCasedataRow["Depth"] = depth;
                    TestCasedataRow["TestSuiteId"] = childSuite.Id;
                    TestCasedataRow["TestSuiteTitle"] = childSuite.Title;
                    TestCasedataRow["TestCaseCount"] = childSuite.TestCaseCount;
                    TestCasedataRow["TestCaseID"] = childSuite.TestCases[i].Id;
                    TestCasedataRow["TestCaseTitle"] = childSuite.TestCases[i].Title;
                    TestCasedataRow["TestCaseStatus"] = childSuite.TestCases[i].TestCase.State;
                    TestCasedataRow["ParentTestSuite"] = childSuite.TestCases[i].ParentTestSuite.Id;
                    TestCasedataRow["AutomationStatus"] =
                        childSuite.TestCases[i].TestCase.CustomFields["Microsoft.VSTS.TCM.AutomationStatus"].Value;
                    var implementation = (ITmiTestImplementation)childSuite.TestCases[i].TestCase.Implementation;

                    if (implementation != null)
                    {
                        TestCasedataRow["AutomationStatusTestType"] = implementation.TestType;
                        TestCasedataRow["AutomationStatusTestId"] = implementation.TestId.ToString();
                        TestCasedataRow["AutomationStatusStorage"] = implementation.Storage;
                        TestCasedataRow["AutomationStatusTestName"] = implementation.TestName;
                    }

                    TestCasedataRow["LastUpdate"] = this.UpdateDateTime;

                    this.TestSuiteDataTable.Rows.Add(TestCasedataRow);
                }

                // Loop for child - child
                this.ExportToDataTable(childSuite.SubSuites, depth + 1);
            }
        }

        private void InitTestSuiteDataTable()
        {
            this.TestSuiteDataTable.Columns.Add("TestPlanID", typeof(int));
            this.TestSuiteDataTable.Columns.Add("TestPlanName", typeof(string));
            this.TestSuiteDataTable.Columns.Add("Depth", typeof(int));
            this.TestSuiteDataTable.Columns.Add("ParentTestSuite", typeof(String));
            this.TestSuiteDataTable.Columns.Add("TestSuiteId", typeof(int));
            this.TestSuiteDataTable.Columns.Add("TestSuiteTitle", typeof(String));
            this.TestSuiteDataTable.Columns.Add("TestCaseCount", typeof(int));
            this.TestSuiteDataTable.Columns.Add("TestCaseID", typeof(int));
            this.TestSuiteDataTable.Columns.Add("TestCaseTitle", typeof(String));
            this.TestSuiteDataTable.Columns.Add("TestCaseStatus", typeof(String));
            this.TestSuiteDataTable.Columns.Add("AutomationStatus", typeof(String));
            this.TestSuiteDataTable.Columns.Add("AutomationStatusTestType", typeof(String));
            this.TestSuiteDataTable.Columns.Add("AutomationStatusTestId", typeof(String));
            this.TestSuiteDataTable.Columns.Add("AutomationStatusStorage", typeof(String));
            this.TestSuiteDataTable.Columns.Add("AutomationStatusTestName", typeof(String));
            this.TestSuiteDataTable.Columns.Add("LastUpdate", typeof(DateTime));
        }

        private void Traversal(ITestSuiteCollection suitesCollection, int depth)
        {
            foreach (IStaticTestSuite childSuite in suitesCollection)
            {
                Console.WriteLine("Depth : {0}", depth);

                Console.WriteLine("Suite Title : {0}", childSuite.Title);
                Console.WriteLine("Suite Id: {0}", childSuite.Id);
                Console.WriteLine("Suite Test Case Count: {0}", childSuite.TestCaseCount);

                for (int i = 0; i < childSuite.TestCaseCount; i++)
                {
                    Console.WriteLine("Suite Test Case ID: {0}", childSuite.TestCases[i].Id);
                    Console.WriteLine("Suite Test Case Title: {0}", childSuite.TestCases[i].Title);
                }

                // Loop for child - child
                this.Traversal(childSuite.SubSuites, depth + 1);
            }
        }

        private void UpdateTestSuiteDB(DataTable dt)
        {
            try
            {
                var sqlConnectionObj =
                    (SqlConnection)DatabaseConnectionFactory.CreateConnection(this.connectionString, this.providerName);
                sqlConnectionObj.Open();

                var bulkCopy = new SqlBulkCopy(
                    sqlConnectionObj, 
                    SqlBulkCopyOptions.TableLock | SqlBulkCopyOptions.FireTriggers
                    | SqlBulkCopyOptions.UseInternalTransaction, 
                    null);
                bulkCopy.DestinationTableName = this.DBTestSuiteTableName;
                bulkCopy.WriteToServer(dt);
                sqlConnectionObj.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        #endregion
    }
}